<?php
App::import('vendor', 'TCPDF', array('file' => 'tcpdf/tcpdf.php'));
/**
 * TCPDF extended for costum headers and footers
 *
 */
class LilPdfReport extends TCPDF {
/**
 * PDF options
 *
 * @var array
 */
	protected $_options = array();
/**
 * __construct
 *
 * @return void
 */
	public function __construct($options) {
		$this->options($options);
		parent::__construct($options['orientation'], $options['unit'], $options['format'],
			$options['unicode'], $options['encoding'], $options['diskcache']);
	}
/**
 * Header
 *
 * @return void
 */
	function Header() {
		$this->SetFont($this->_options['font'], '', $this->_options['font_size']);
		
		if (!empty($this->_options['header']['lines'])) foreach ($this->_options['header']['lines'] as $l) {
			if (isset($l['image']) && is_string($l['image']) && file_exists($l['image'])) {
				$margins = $this->getMargins();
				$this->Image($l['image'], $margins['left'], 0, $this->getPageWidth() - $margins['left'] - $margins['right']);
			} else if (isset($l['image']) && is_array($l['image']) && file_exists(reset($l['image']))) {
				call_user_func_array(array($this, 'Image'), $l['image']);
			} else if (isset($l['text']) && is_array($l['text'])) {
				call_user_func_array(array($this, 'Text'), $l['text']);
			} else if (isset($l['write']) && is_array($l['write'])) {
				call_user_func_array(array($this, 'Write'), $l['write']);
			}
		}
	}
/**
 * Footer
 *
 * @return void
 */
	function Footer() {
		$this->SetFont($this->_options['font'], '', $this->_options['font_size']);
		if (!empty($this->_options['footer']['lines'])) foreach ($this->_options['footer']['lines'] as $l) {
			if (isset($l['image']) && is_string($l['image']) && file_exists($l['image'])) {
				$margins = $this->getMargins();
				$this->Image($l['image'], $margins['left'], 275, $this->getPageWidth() - $margins['left'] - $margins['right']);
			} else if (isset($l['image']) && is_array($l['image']) && file_exists(reset($l['image']))) {
				call_user_func_array(array($this, 'Image'), $l['image']);
			} else if (isset($l['text']) && is_array($l['text'])) {
				call_user_func_array(array($this, 'Text'), $l['text']);
			} else if (isset($l['write']) && is_array($l['write'])) {
				call_user_func_array(array($this, 'Write'), $l['write']);
			}
		}
	}
/**
 * Options
 *
 * @param array $options
 * @return mixed
 */
	public function options($values = null) {
		if ($values === null) {
			return $this->_options;
		}
		$this->_options = $values;
		return $this;
	}
}
/**
 * LilReport main class
 *
 */
class LilReport {
/**
 * PDF options
 *
 * @var array
 */
	protected $options = array();
/**
 * PDF class
 *
 * @var object
 */
	private $_pdf = null;
/**
 * construct method
 *
 * @return void
 */
	public function __construct($template = null) {
		$_defaults = array(
			'orientation' => PDF_PAGE_ORIENTATION, // 'P' or 'L'
			'unit'        => PDF_UNIT,             // default 'mm'
			'format'      => PDF_PAGE_FORMAT,      // default 'A4'
			'unicode'     => true,
			'encoding'    => 'UTF-8',
			'diskcache'   => false,
			'creator'     => PDF_CREATOR,
			'author'      => PDF_AUTHOR,
			'title'       => PDF_HEADER_TITLE,
			'subject'     => PDF_HEADER_STRING,
			'keywords'    => '',
			'font'        => 'dejavusans',
			'font_size'   => 10,
			'language'    => array(
				'a_meta_charset'  => 'UTF-8',
				'a_meta_dir'      => 'ltr',
				'a_meta_language' => 'sl'
			),
			'margin'     => array(
				'left'  => PDF_MARGIN_LEFT,
				'top'   => PDF_MARGIN_TOP,
				'right' => PDF_MARGIN_RIGHT
			),
			'header'      => array(
				'margin' => PDF_MARGIN_HEADER, // minimum distance between header and top page margin
				'lines'  => array(
					array('image' => APP . 'uploads' . DS . 'report_header.png')
				)
			),
			'footer'      => array(
				'margin' => PDF_MARGIN_FOOTER, // minimum distance between footer and bottom page margin
				'lines'  => array(
					array('image' => APP . 'uploads' . DS . 'report_footer.png')
				)
			),
			'layout'      => 'pdf',
			'template'    => '',
			'view'        => 'Lil.LilPdfView',
			'helpers'     => array(),
			'viewVars'    => array()
		);
		
		if (is_string($template)) {
			$options = (array)Configure::read('Lil.Report.' . $template);
		} else {
			$options = $template;
		}
		
		$this->options = Set::merge($_defaults, (array)$options);
		$this->options = $this->callPluginHandlers('init_report', $this->options);
		$this->_pdf = new LilPdfReport($this->options);
		
		// set document information
		$this->_pdf->SetCreator($this->options['creator']);
		$this->_pdf->SetAuthor($this->options['author']);
		$this->_pdf->SetTitle($this->options['title']);
		$this->_pdf->SetSubject($this->options['subject']);
		$this->_pdf->SetKeywords($this->options['keywords']);
		
		// lang
		$this->_pdf->setLanguageArray($this->options['language']);
		
		//set auto page breaks
		$this->_pdf->SetAutoPageBreak(true, $this->options['footer']['margin']);
		
		// set font
		$this->_pdf->SetFont($this->options['font'], '', $this->options['font_size']);

		$this->_pdf->SetCellPadding(2);
		
		// margins
		$this->_pdf->SetMargins(
			$this->options['margin']['left'],
			$this->options['margin']['top'],
			$this->options['margin']['right'],
			true // keep margins
		);
		
		if (empty($this->options['header'])) {
			$this->_pdf->SetPrintHeader(false);
		} else {
			$this->_pdf->SetHeaderMargin($this->options['header']['margin']);
		}
		
		if (empty($this->options['footer'])) {
			$this->_pdf->SetPrintFooter(false);
		} else {
			$this->_pdf->SetFooterMargin($this->options['footer']['margin']);
		}
		
		// add a page (call header)
		$this->_pdf->AddPage();
	}
/**
 * Template and layout
 *
 * @param mixed $template Template name or null to not use
 * @param mixed $layout Layout name or null to not use
 * @return mixed
 */
	public function template($template = false, $layout = false) {
		if ($template === false) {
			return array(
				'template' => $this->options['template'],
				'layout' => $this->options['layout']
			);
		}
		
		// set template and layout
		$this->options['template'] = $template;
		if ($layout !== false) {
			$this->options['layout'] = $layout;
		}
		
		return $this;
	}
/**
 * View class for render
 *
 * @param string $viewClass
 * @return mixed
 */
	public function viewRender($viewClass = null) {
		if ($viewClass === null) {
			return $this->options['view'];
		}
		$this->options['view'] = $viewClass;
		return $this;
	}
/**
 * Helpers to be used in render
 *
 * @param array $helpers
 * @return mixed
 */
	public function helpers($helpers = null) {
		if ($helpers === null) {
			return $this->options['helpers'];
		}
		$this->options['helpers'] = (array)$helpers;
		return $this;
	}
/**
 * Variables to be set on render
 *
 * @param array $viewVars
 * @return mixed
 */
	public function set($viewVars = null, $varValue = null) {
		if ($viewVars === null) {
			return $this->options['viewVars'];
		}
		
		if (!is_null($varValue)) {
			$this->options['viewVars'][$viewVars] = $varValue;
		} else {
			$this->options['viewVars'] = Set::merge($this->options['viewVars'] , (array)$viewVars);
		}
		return $this;
	}
/**
 * Reset all EmailComponent internal variables to be able to send out a new email.
 *
 * @return CakeEmail $this
 */
	public function reset() {
		/*$this->_layout = 'default';
		$this->_template = '';
		$this->_viewRender = 'View';*/
		$this->options['viewVars'] = array();
		return $this;
	}
/**
 * Add new page
 *
 * @return CakeEmail $this
 */
	public function AddPage() {
		$this->_pdf->AddPage();
		return $this;
	}
/**
 * Init view class
 *
 * @return void
 */
	public function init() {
		$viewClass = $this->options['view'];

		if ($viewClass !== 'View') {
			list($plugin, $viewClass) = pluginSplit($viewClass, true);
			App::uses($viewClass, $plugin . 'View');
		}

		$this->View = new $viewClass(null);
		$this->View->helpers = $this->options['helpers'];
		$this->View->viewPath = 'Reports';
		$this->View->layoutPath = 'Reports';
		
		if (is_callable(array($this->View, 'setPdf'))) $this->View->setPdf($this->_pdf);
	}
/**
 * Render method
 *
 * @param string $fileName The name of the file when saved. Note that special characters are removed and blanks characters are replaced with the underscore character.
 * @param string $dest Destination where to send the document. It can take one of the following values:
 *                     <ul><li>I: send the file inline to the browser (default). The plug-in is used if available. The name given by name is used when one selects the "Save as" option on the link generating the PDF.</li>
 *                     <li>D: send to the browser and force a file download with the name given by name.</li>
 *                     <li>F: save to a local server file with the name given by name.</li>
 *                     <li>S: return the document as a string. name is ignored.</li>
 *                     <li>FI: equivalent to F + I option</li>
 *                     <li>FD: equivalent to F + D option</li></ul>
 */
	public function render($fileName = null, $options = array()) {
		$default_options = array('dest' => 'I', 'template' => $this->options['template'], 'layout' => $this->options['layout']);
		if (!is_array($options)) $options = array('dest' => $options);
		$options = array_merge($default_options, $options);
		
		// init view it it does not exist
		if (empty($this->View)) {
			$this->init();
		} else {
			$this->View->hasRendered = false;
		}
		
		list($templatePlugin, $template) = pluginSplit($options['template']);
		list($layoutPlugin, $layout) = pluginSplit($options['layout']);
		if ($templatePlugin) {
			$this->View->plugin = $templatePlugin;
		} elseif ($layoutPlugin) {
			$this->View->plugin = $layoutPlugin;
		}
		
		// set view vars
		$this->View->viewVars = $this->options['viewVars'];
		
		$this->options = $this->callPluginHandlers('before_render_report', $this->options);
		
		$rendered = $this->View->render($template, $layout);
		
		// output body
		$rendered = explode('<!-- NEW PAGE -->', $rendered);
		
		foreach ($rendered as $page) {
			$this->_pdf->writeHTML($page);
			if (sizeof($rendered) > 1) {
				$this->_pdf->AddPage();
			}
		}
		
		// optionally output file
		if ($fileName) {
			$this->output($fileName, $options['dest']);
		}
	}
/**
 * output method
 *
 * @return mixed
 */
	public function output($fileName, $dest = 'I') {
		$this->_pdf->Output($fileName . '.pdf', $dest);
	}
/**
 * callPluginHandlers method
 *
 * @return mixed
 */
	public function callPluginHandlers($handler, $data = null) {
		$registry = LilPluginRegistry::getInstance();
		return $registry->callPluginHandlers($this, $handler, $data);
	}
}
